#include "SyntaxEditor.h"

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QMap>

#include <QDomElement>
#include <QDomDocument>

#include "juffed/Log.h"
#include "ColorButton.h"
//#include "juffed/AppInfo.h"

	struct Style {
		Style(const QColor& c = QColor(), const QColor& bgc = QColor(), bool b = false, bool i = false) {
			color = c;
			bgColor = bgc;
			bold = b;
			italic = i;
		}

		bool bold;
		bool italic;
		QColor color;
		QColor bgColor;
	};

	typedef QMap<QString, Style> StyleMap;
	
	struct Scheme {
		QString name;
		Style defaultStyle;
		StyleMap styleMap;
	};

class SyntaxEditor::Interior {
public:
	Interior() {
	}
	
	QMap<QString, Scheme> schemes_;
	ColorButton* colorBtn_;
	ColorButton* bgColorBtn_;
};

SyntaxEditor::SyntaxEditor() : QWidget() {
	ui.setupUi(this);
	int_ = new Interior();
	
	int_->colorBtn_ = new ColorButton(ui.colorBtn, QColor());
	int_->bgColorBtn_ = new ColorButton(ui.bgColorBtn, QColor());
	readStyles();
	
	connect(ui.syntaxCmb, SIGNAL(activated(const QString&)), SLOT(slotSchemeActivated(const QString&)));
	connect(ui.schemeList, SIGNAL(currentTextChanged(const QString&)), SLOT(slotItemActivated(const QString&)));


	ui.syntaxCmb->addItems(int_->schemes_.keys());
	ui.syntaxCmb->setCurrentIndex(0);
}

SyntaxEditor::~SyntaxEditor() {
	delete int_;
}

void SyntaxEditor::readStyles() {
	QString path(QDir::homePath() + "/.config/juff/hlschemes/");
	QDir dir(path);
	QStringList list = dir.entryList(QStringList() << "*.xml", QDir::Files);
	qDebug() << list;
	foreach (QString file, list) {
		readStyle(dir.absoluteFilePath(file));
	}
}




bool stringToBool(const QString& str) {
	return (str.compare("true") == 0 || str.compare("yes") == 0 || str.compare("1") == 0);
}

QColor stringToColor(const QString& str) {
	return QVariant(str).value<QColor>();
}

void parseScheme(const QDomElement& schEl, Scheme& scheme) {
	scheme.name = schEl.attribute("name", "");
	if (scheme.name.isEmpty())
		return;

	QDomNode styleNode = schEl.firstChild();

	QString defColorStr = schEl.attribute("defaultColor", "");
	QString defBgColorStr = schEl.attribute("defaultBgColor", "");
	QString defBoldStr = schEl.attribute("defaultBold", "false");
	QString defItalicStr = schEl.attribute("defaultItalic", "false");
	
	scheme.defaultStyle = Style(stringToColor(defColorStr), stringToColor(defBgColorStr), 
			stringToBool(defBoldStr), stringToBool(defItalicStr));

	while ( !styleNode.isNull() ) {
		QDomElement styleEl = styleNode.toElement();
		if ( styleEl.tagName().toLower().compare("style") == 0 ) {
			Style style;
			QString name = styleEl.attribute("name", "");
			if ( !name.isEmpty() ) {
//				qDebug() << name;
				style.color = stringToColor(styleEl.attribute("color", defColorStr));
				style.bgColor = stringToColor(styleEl.attribute("bgColor", defBgColorStr));
				style.bold = stringToBool(styleEl.attribute("bold", defBoldStr));
				style.italic = stringToBool(styleEl.attribute("italic", defItalicStr));
				
//				qDebug() << style.color;
				scheme.styleMap[name] = style;
			}
		}

		styleNode = styleNode.nextSibling();
	}
}

void SyntaxEditor::readStyle(const QString& fileName) {
	QDomDocument doc("JuffScheme");
//	QString fileName = QString("%1.xml").arg(nm);
//	fileName = AppInfo::configDirPath() + "/hlschemes/" + fileName;

	Log::debug(QString("Reading custom style from file '%1'...").arg(fileName), true);

	QFile file(fileName);
	if ( !file.open(QIODevice::ReadOnly) ) {
		Log::debug(QString("Can't open file '%1'").arg(fileName));
		return;
	}
	else {
		Log::debug(QString("File '%1' opened successfully").arg(fileName), true);
	}

	QString err;
	int errLine, errCol;
	if ( !doc.setContent(&file, &err, &errLine, &errCol) ) {
		Log::debug(QString("File %1: XML reading error: '%2', line %3, column %4")
				.arg(fileName).arg(err).arg(errLine).arg(errCol));
		file.close();
		return;
	}
	else {
		Log::debug(QString("File '%1' was parsed successfully").arg(fileName), true);
	}
	
	file.close();

	QDomElement docElem = doc.documentElement();
	QDomNode schNode = docElem.firstChild();
	while( !schNode.isNull() ) {
		QDomElement schEl = schNode.toElement();
		if( !schEl.isNull() ) {
			if ( schEl.tagName().toLower().compare("scheme") == 0 ) {

				Scheme scheme;
				parseScheme(schEl, scheme);

				if ( !scheme.name.isEmpty() ) {
					int_->schemes_[scheme.name] = scheme;
					qDebug() << "Added scheme" << scheme.name;
				}
//				if ( schEl.hasAttribute("curLineColor") && schEl.hasAttribute("name") ) {
//					QColor curLineColor = stringToColor(schEl.attribute("curLineColor"));
//					QString schName = schEl.attribute("name");
//					curLineColors_[schName] = curLineColor;
//				}
//				if ( schEl.hasAttribute("selectionBgColor") && schEl.hasAttribute("name") ) {
//					QColor selectionBgColor = stringToColor(schEl.attribute("selectionBgColor"));
//					QString schName = schEl.attribute("name");
//					selectionBgColors_[schName] = selectionBgColor;
//				}
			}
		}
		schNode = schNode.nextSibling();
	}
}

void SyntaxEditor::slotSchemeActivated(const QString& schemeName) {
	Scheme sch = int_->schemes_[schemeName];
	ui.schemeList->clear();
	ui.schemeList->addItems(sch.styleMap.keys());
	ui.schemeList->setCurrentRow(0);
}

void SyntaxEditor::slotItemActivated(const QString& rule) {
	
	// save old colors
	
	
	// set new colors 
	Scheme scheme = int_->schemes_[ui.syntaxCmb->currentText()];
	Style style = scheme.styleMap[rule];
	
	if (style.color.isValid()) {
		ui.customColorChk->setChecked(true);
		int_->colorBtn_->setColor(style.color);
	}
	else {
		ui.customColorChk->setChecked(false);
		int_->colorBtn_->setColor(QColor());
	}
	
	if (style.bgColor.isValid()) {
		ui.customBgColorChk->setChecked(true);
		int_->bgColorBtn_->setColor(style.bgColor);
	}
	else {
		ui.customBgColorChk->setChecked(false);
		int_->bgColorBtn_->setColor(QColor());
	}

	ui.boldChk->setChecked(style.bold);
	ui.italicChk->setChecked(style.italic);
}
